#include "math.h"
#include "Convertion.h"


/*!
 * \brief 从2进制的QString类型字符串转换到16进制的QString类型字符串
 *
 * \param Qstring s 2进制的QString类型字符串
 *
 * \return 16进制的QString类型字符串
 *
 * Detail here!!!
 */
QString Convertion::binaryToHex(QString s){
    bool ok;
    int val = s.toInt(&ok,2);
    return decimalToHex4Bit(QString::number(val,10).toInt());
}

/*!
 * \brief 从std::string类型 转换到  int类型
 *
 * \param a const std::string &str 需要转换的字符串
 *
 * \return \a int 转换后的int型变量
 *
 * Detail here!!!
 */
int Convertion::stringToInt(const std::string &str) {
    const char *buf=str.c_str();
    int i=atoi(buf);
    return i;
}

/*!
* \brief 从std::string类型 转换到  double类型
*
* \param a const 从std::string &str 需要转换的字符串
*
* \return \a double 转换后的double变量
*
* Detail here!!!
*/
double Convertion::stringToDouble(const std::string &str) {
    const char *buf=str.c_str();
    double i=atof(buf);
    return i;
}

/*!
* \brief 从int类型 转换到  从std::string类型
*
* \param a int i 需要转换的int型变量
*
* \return \a 从std::string 转换后的变量
*
* Detail here!!!
*/
const std::string Convertion::intToString(int i) {
    char *buf;
    buf=new char[20];
    //    memset(buf, 0, 20);
    sprintf(buf, "%d", i);
    const std::string str=buf;
    return str;
}

/*!
 * \brief 从double类型 转换到  std::string类型
 *
 * \param double i 需要转换的变量，int j 小数点后保留的位数
 *
 * \return \a std::string 转换后的变量
 *
 * Detail here!!!
 */
const std::string Convertion::doubleToString(double i, int j) {
    char *buf;
    buf=new char[20];
    //    memset(buf, 0, 20);
    sprintf(buf, "%.*f", j, i);
    const std::string str=buf;
    return str;
}

/*!
 * \brief 四舍五入转换函数
 *
 * \param a double convertobject 需要转换对象,
 *          int n 表示小数点后几位开始四舍五入
 *
 * \return \a double 四舍五入之后的数
 *
 * Detail here!!!
 */
double Convertion::roundingOffConvert(double convertobject, int n) {
    double dd = pow (10, n);
    double dt = convertobject * dd;
    double df = ceil(dt) - dt - 0.5f;

    if (df > 0.00000001f)
        return floor(dt) / dd; //下靠
    else if (df < -0.00000001f)
        return ceil(dt) / dd; //上靠
    else if (convertobject > 0)
        return ceil(dt) / dd; //正数、五入
    else
        return floor(dt) / dd; //负数、五入
}

/*!
 * \brief 字符串类型转换函数
 *
 * \param a string s 需要转换字符串,
 *
 * \return \a  QString类型的字符串
 *
 * Detail here!!!
 */
QString Convertion::stringToQString(std::string s){
    return QString::fromStdString(s);
}

/*!
 * \brief 进制转换函数
 *
 * \param int dec 需要转换的十进制整数
 *
 * \return \a  长度为4的QString类型的16进制字符串
 *
 * Detail here!!!
 */
QString Convertion::decimalToHex4Bit(int dec){
    Convertion tmp;

    std::string out;
    std::stringstream s1;
    std::stringstream s2;
    std::string result;

    s1 << std::hex <<dec;
    s1 >> out ;
    transform(out.begin(), out.end(), out.begin(), ::toupper);
    s2 << std::setw(4) << std::setfill('0') << out;
    s2 >> result;

    return tmp.stringToQString(result);

};


/*!
 * \brief 进制转换函数
 *
 * \param int dec 需要转换的十进制整数
 *
 * \return \a  长度为2的QString类型的16进制字符串
 *
 * Detail here!!!
 */
QString Convertion::decimalToHex2Bit(int dec){
    Convertion tmp;

    std::string out;
    std::stringstream s1;
    std::stringstream s2;
    std::string result;

    s1 << std::hex <<dec;
    s1 >> out ;
    transform(out.begin(), out.end(), out.begin(), ::toupper);
    s2 << std::setw(2) << std::setfill('0') << out;
    s2 >> result;

    return tmp.stringToQString(result);

};

/*!
 * \brief 进制转换函数
 *
 * \param int dec 需要转换的十进制整数
 *
 * \return \a  长度为1的QString类型的16进制字符串
 *
 * Detail here!!!
 */
QString Convertion::decimalToHex1Bit(int dec){
    Convertion tmp;

    std::string out;
    std::stringstream s1;
    std::stringstream s2;
    std::string result;

    s1 << std::hex <<dec;
    s1 >> out ;
    transform(out.begin(), out.end(), out.begin(), ::toupper);
    s2 << std::setw(1) << std::setfill('0') << out;
    s2 >> result;

    return tmp.stringToQString(result);

};


/*!
 * \brief 进制转换函数
 *
 * \param string hexString 需要转换的十六进制字符串
 *
 * \return \a  十进制字符串
 *
 * Detail here!!!
 */
QString Convertion::hexToDec(std::string hexString)
{
    QString s = QString::number(std::stoi(hexString, nullptr, 16));
    return s;
}

/*!
 * \brief 进制转换函数
 *
 * \param string binaryString 需要转换的二进制字符串
 *
 * \return \a  十进制字符串
 *
 * Detail here!!!
 */
QString Convertion::binaryToDec(std::string binaryString)
{

    QString s = QString::number(std::stoi(binaryString, nullptr, 2));
    return s;
}

/*!
 * \brief 反应板数据转换函数
 *
 * \param ReactionPlate reactionPlate 包含反应板配置数据的结构体
 *
 * \return QString类型的16进制字符串
 *
 * Detail here!!!
 */
QString Convertion::getReactionPlateData(ReactionPlate reactionPlate,QString experimentId){
    QString sendData = "";
    //    sendData = sendData + decimalToHex4Bit(experimentId.toInt()); //添加实验id
    if(reactionPlate.consumables.contains("卡式")){
        sendData += "0001";
    }else if(reactionPlate.consumables.contains("芯片")){
        sendData += "0002";
    }else if(reactionPlate.consumables.contains("管式")){
        sendData += "0003";
    }else if(reactionPlate.consumables.contains("圆型32")){
        sendData += "0004";
    }


    for(int i = 0;i < 32;i ++){
            sendData += decimalToHex2Bit(i + 1);  //样本孔位
            QString line;
            QString FAM = "0";
            QString VIC = "0";
            QString ROX = "0";
            QString CY5 = "0";
            for(int j = 0;j < 4;j ++){
                if(reactionPlate.targetList[i][j].reporter == "FAM"){
                    FAM = "1";
                }else if(reactionPlate.targetList[i][j].reporter == "VIC"){
                    VIC = "1";
                }else if(reactionPlate.targetList[i][j].reporter == "ROX"){
                    ROX = "1";
                }else if(reactionPlate.targetList[i][j].reporter == "CY5"){
                    CY5 = "1";
                }
            }
            line += CY5 + ROX + VIC + FAM;
            line += "0000";
            bool is_ok;
            sendData += decimalToHex1Bit(line.mid(4,4).toInt(&is_ok,2)).toLower();
            sendData += decimalToHex1Bit(line.mid(0,4).toInt(&is_ok,2)).toLower();
    }
    sendData += "203b"; //添加分号
    return sendData;
}


QString Convertion::getProcedureData(QHash<QHash<QString,QString>,QList<QHash<QString,QString>>> data,QString experimentId)
{
    QString sendData;

    QList<QHash<QString,QString>> stages;

    QHash<QHash<QString,QString>,QList<QHash<QString,QString>>>::const_iterator it;

    int holding_num = 1;
    int pcr_stage = 1;
    int dissolution_curve_stage = 1;

    for (it=data.begin(); it!=data.end();++it)
    {
        stages.append(it.key());
    }

    for(int i = 0;i < stages.size();i ++){
        for(int j = i + 1;j < stages.size();j ++){
            int k = stages[i]["stage_order"].toInt();
            int l = stages[j]["stage_order"].toInt();
            if(k > l){
                QHash<QString,QString> t = stages[i];
                stages[i] = stages[j];
                stages[j] = t;
            }
        }
    }


    int sum = stages.size();
    sendData = sendData + decimalToHex4Bit(sum); //添加循环体总数
    QList<QHash<QString,QString>>::const_iterator list;

    for(int i = 0;i < stages.size();i ++){
        if(stages[i]["name"] == HOLDING_STAGE){
            sendData += "0001";
            sendData += decimalToHex4Bit(holding_num); //添加编号
            // 编号增加
            holding_num++;
            int cnt = 1;
            for (list = (data.value(stages[i])).begin(); list!=(data.value(stages[i])).end(); ++list)
            {
                sendData = sendData + decimalToHex4Bit(cnt); //添加步骤
                QString temperature = QString::number(list->value("temperature").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(temperature.toInt()); //添加温度

                QString duration = QString::number(list->value("duration").toFloat());
                sendData = sendData + decimalToHex4Bit(duration.toInt()); //添加持续时间

                QString rate = QString::number(list->value("rate").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(rate.toInt()); //添加升温速率

                if(list->value("is_fluorescence") == "1") //添加是否开启荧光采集
                {
                    sendData = sendData + "0001"; //开启荧光采集
                }
                else
                {
                    sendData = sendData + "0000";    //未开启荧光采集
                }
                cnt ++;
            }
            sendData = sendData + "0001";
            sendData = sendData + "203B"; //添加分隔符
        }else if(stages[i]["name"] == PCR_STAGE){
            sendData += "0002";
            sendData += decimalToHex4Bit(pcr_stage); //添加编号
            // 编号增加
            pcr_stage++;
            int cnt = 1;
            for (list = (data.value(stages[i])).begin(); list!=(data.value(stages[i])).end(); ++list)
            {
                sendData = sendData + decimalToHex4Bit(cnt); //添加步骤
                QString temperature = QString::number(list->value("temperature").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(temperature.toInt()); //添加温度

                QString duration = QString::number(list->value("duration").toFloat());
                sendData = sendData + decimalToHex4Bit(duration.toInt()); //添加持续时间

                QString rate = QString::number(list->value("rate").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(rate.toInt()); //添加升温速率

                if(list->value("is_fluorescence") == "1") //添加是否开启荧光采集
                {
                    sendData = sendData + "0001"; //开启荧光采集
                }
                else
                {
                    sendData = sendData + "0000";    //未开启荧光采集
                }
                cnt ++;
            }

            sendData = sendData + decimalToHex4Bit(stages[i]["cycle_number"].toInt());
            sendData = sendData + "203B"; //添加分隔符
        }else if(stages[i]["name"] == DISSOLUTION_CURVE_STAGE){
            sendData += "0003";
            sendData += decimalToHex4Bit(dissolution_curve_stage); //添加编号
            // 编号增加
            dissolution_curve_stage++;
            int cnt = 1;
            for (list = (data.value(stages[i])).begin(); list!=(data.value(stages[i])).end(); ++list)
            {

                sendData = sendData + decimalToHex4Bit(cnt); //添加步骤

                QString temperature = QString::number(list->value("temperature").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(temperature.toInt()); //添加温度

                QString duration = QString::number(list->value("duration").toFloat());
                sendData = sendData + decimalToHex4Bit(duration.toInt()); //添加持续时间

                QString rate = QString::number(list->value("rate").toFloat() * 10);
                sendData = sendData + decimalToHex4Bit(rate.toInt()); //添加升温速率

                if(list->value("is_fluorescence") == "1") //添加是否开启荧光采集
                {
                    sendData = sendData + "0001"; //开启荧光采集
                }
                else
                {
                    sendData = sendData + "0000";    //未开启荧光采集
                }
                cnt ++;
            }
            sendData = sendData + "0001";
            sendData = sendData + "203B"; //添加分隔符
        }
    }

    sendData = sendData.remove(sendData.size() - 4,4) + "203B";
    qDebug() << sendData;
    return sendData;

}
